package edu.hit.crawler.util;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Hashtable;
import java.util.List;
import java.util.Stack;

import org.apache.mina.filter.buffer.BufferedWriteFilter;

import edu.hit.crawler.io.CrawItem;

/**
 * Host shuffle makes the urls that share the same host name will have the
 * largest distance in the crawl queue.
 * 
 * @author Song Liu (Lamfeeling@126.com)
 * 
 */
public class HostShuffle {

	static class Item implements Comparable<Item> {
		int age;
		String host;

		@Override
		public String toString() {
			return host + "	" + age;
		}

		@Override
		public int compareTo(Item o) {
			return age - o.age;
		}

	}

	public static List<CrawItem> shuffle(List<CrawItem> origin) {

		Hashtable<String, Stack<CrawItem>> table = new Hashtable<String, Stack<CrawItem>>();

		long startTime = System.currentTimeMillis();
		for (CrawItem u : origin) {
			URL url;
			try {
				url = new URL(u.getUrl());
			} catch (MalformedURLException e) {
				e.printStackTrace();
				System.out.println(u.getUrl());
				continue;
			}
			if (table.get(url.getHost()) == null) {
				table.put(url.getHost(), new Stack<CrawItem>());
			}
			table.get(url.getHost()).add(u);
		}

		ArrayList<Item> hosts = new ArrayList<Item>(table.size());
		for (String h : table.keySet()) {
			Item i = new Item();
			i.age = 0;
			i.host = h;
			hosts.add(i);
		}

		ArrayList<CrawItem> res = new ArrayList<CrawItem>();
		int age = 1;
		while (res.size() != origin.size()) {

			CrawItem it = table.get(hosts.get(0).host).pop();
			res.add(it);
			hosts.get(0).age = age;

			if (table.get(hosts.get(0).host).size() == 0) {
				table.remove(hosts.get(0).host);
				hosts.remove(0);
			}
			Collections.sort(hosts);
			age++;
		}
		System.out.println("\n" + origin.size() + " urls shuffle escape : "
				+ (System.currentTimeMillis() - startTime) + " ms.\n");
		return res;
	}

	/**
	 * @param args
	 * @throws IOException
	 */
	public static void main(String[] args) throws IOException {

		List<CrawItem> l = new ArrayList<CrawItem>();

		BufferedReader br = new BufferedReader(new FileReader("in"));
		BufferedWriter wr1 = new BufferedWriter(new FileWriter("out1"));
		BufferedWriter wr2 = new BufferedWriter(new FileWriter("out2"));
		String line;
		while ((line = br.readLine()) != null) {
			line = line.split(" ")[1];
			
			if (line.startsWith("http"))
				l.add(new CrawItem(line, CrawItem.SUCCESS));
		}
		l = shuffle(l);
		for (CrawItem it : l) {
			wr1.write(it.getUrl() + "\n");
		}

		long startTime = System.currentTimeMillis();

		Collections.sort(l, new CrawItemComparator());

		System.out.println("\n" + l.size() + " escape : "
				+ (System.currentTimeMillis() - startTime) + " ms.\n");
		for (CrawItem it : l) {

			wr2.write(it.getUrl() + "\n");
		}
	}

}
